package com.example.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.example.entity.vo.response.WeatherVO;
import com.example.service.WeatherService;
import com.example.utils.Const;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;

/**
 * @Author: shenjianZ
 * @Date: 2024/4/30 下午2:58
 * @Description:
 */

@Service
public class WeatherServiceImpl implements WeatherService {

    @Resource
    RestTemplate rest;

    @Resource
    StringRedisTemplate template;

    @Value("${spring.weather.accessKey}")
    String accessKey;

    public WeatherVO fetchWeather(double longitude, double latitude){
        return fetchFromCache(longitude, latitude);
    }

    private WeatherVO fetchFromCache(double longitude, double latitude){
        JSONObject geo = this.decompressStringToJSON(rest.getForObject(
                "https://geoapi.qweather.com/v2/city/lookup?location="+longitude+","+latitude+"&key="+accessKey, byte[].class));
        if(geo == null) return null;
        JSONObject location = geo.getJSONArray("location").getJSONObject(0);
        int id = location.getInteger("id");
        String key = Const.FORUM_WEATHER_CACHE + id;
        String cache = template.opsForValue().get(key);
        if(cache != null)
            return JSONObject.parseObject(cache).to(WeatherVO.class);
        WeatherVO vo = this.fetchWeatherFromAPI(id, location);
        if(vo == null) return null;
        template.opsForValue().set(key, JSONObject.from(vo).toJSONString(), 1, TimeUnit.HOURS);
        return vo;
    }

    private WeatherVO fetchWeatherFromAPI(int id, JSONObject location) {
        WeatherVO weatherVo = new WeatherVO();
        weatherVo.setLocation(location);
        // 获取实况天气
        byte[] data = rest.getForObject("https://devapi.qweather.com/v7/weather/now?location=" + id + "&key=" + accessKey, byte[].class);
        JSONObject weatherNow = decompressStringToJSON(data);
        if (weatherNow == null) return null;
        weatherVo.setNow(weatherNow.getJSONObject("now"));
        // 获取未来24小时天气
        data = rest.getForObject("https://devapi.qweather.com/v7/weather/24h?location=" + id + "&key=" + accessKey, byte[].class);
        JSONObject weather24h = decompressStringToJSON(data);
        if (weather24h == null) return null;
        weatherVo.setHourly(new JSONArray(weather24h.getJSONArray("hourly").stream().limit(5).toList()));
        return weatherVo;
    }

    private JSONObject decompressStringToJSON(byte[] data) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(data));
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gzipInputStream.read(buffer)) != -1)
                stream.write(buffer, 0, len);
            stream.close();
            gzipInputStream.close();
            return JSONObject.parseObject(stream.toString());
        } catch (IOException e) {
            return null;
        }

    }
}

